Add get_mode_settings(), set_mode_reserve(); fix get_mode()Add tou reserve methods#37
Open
npdsomerhayes wants to merge 3 commits into
Open
Add get_mode_settings(), set_mode_reserve(); fix get_mode()Add tou reserve methods#37npdsomerhayes wants to merge 3 commits into
npdsomerhayes wants to merge 3 commits into
Conversation
get_mode() had a known-broken TODO: it used runingMode from _switch_status()
which is an unreliable rolling ID, not a stable mode identifier. The
touMinSoc/selfMinSoc/backupMaxSoc fields it read are also incorrect — they
do not reflect the user-visible battery reserve percentages.
This commit fixes all of that by introducing two new methods built on a
newly discovered API endpoint (getGatewayTouListV2), found via MITM
interception of the FranklinWH mobile app.
New: get_mode_settings() -> ModeSettings
POST /hes-gateway/terminal/tou/getGatewayTouListV2
Returns a ModeSettings dataclass listing all three operating modes with
their installation-specific ids, names, reserve SOC percentages, and
which mode is currently active (via current_mode_id / current_work_mode).
ModeSettings.reserves provides a convenient workMode→soc dict.
New: set_mode_reserve(work_mode, soc)
POST /hes-gateway/terminal/tou/updateSocV2
Updates the reserve SOC for a single mode WITHOUT switching to that mode.
Validates work_mode against WORK_MODE_MAP and soc against 0-100 before
making the API call.
Fixed: get_mode() rewritten to use get_mode_settings()
Preserves the existing (mode_name, soc) return signature for backward
compatibility. Now raises InvalidDataException (consistent with the rest
of the library) instead of RuntimeError or KeyError.
New: WORK_MODE_MAP {1: TOU, 2: Self-Consumption, 3: Emergency Backup}
Maps the workMode integers returned by getGatewayTouListV2 and
getDeviceCompositeInfo to the existing MODE_* constants.
New: ModeInfo and ModeSettings dataclasses exported from __init__.py
Notes on the API:
- currendId in the API response is a known typo (not currENTId); preserved as-is
- electricityType=1 is a required parameter for updateSocV2 (purpose unknown)
- Emergency Backup always has editSocFlag=false; the server rejects SOC writes
- The mode ids returned by getGatewayTouListV2 (e.g. 83132, 79680, 77244) are
installation-specific and differ from the hardcoded values in Mode factory
methods (9322/9323/9324) used by updateTouMode — both sets are correct for
their respective endpoints
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The getGatewayTouListV2 API returns soc as a float (e.g. 10.0, 100.0). ModeInfo.soc was declared as int which would cause a type mismatch. Updated to float and aligned the ModeSettings.reserves return annotation. get_mode() docstring return type updated from tuple[str, int] to tuple[str, float] accordingly. Also adds bin/test-tou-reserve.py — a standalone script that exercises get_mode_settings(), get_mode(), and set_mode_reserve() against a real gateway without requiring a Home Assistant installation. Tested successfully against gateway 10060006A02F24170129. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…fier The 'name' field returned by getGatewayTouListV2 is whatever the user named their electricity plan in the FranklinWH app — it is not a fixed or predictable mode label. Only work_mode (1/2/3) reliably identifies the mode type. Updated ModeInfo docstring and test script output accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the long-standing broken
get_mode()and adds two new methods builton a previously undocumented API endpoint discovered via MITM interception
of the FranklinWH mobile app.
get_mode()had aTODOcomment acknowledging it was wrong:runingModefrom_switch_status()is not a stable mode identifier —it appears to be a rolling/schedule ID that changes between polls even
when the mode hasn't changed
touMinSoc/selfMinSoc/backupMaxSocdo not reflect theuser-visible battery reserve percentage
get_mode()raisedKeyErrorNew endpoint:
getGatewayTouListV2POST /hes-gateway/terminal/tou/getGatewayTouListV2?showType=1
Returns all three operating modes with their reserve SOC percentages and
identifies the currently active mode via
currendId(sic — API typo):{ "result": { "currendId": 83132, "list": [ {"id": 83132, "workMode": 1, "name": "Free power", "soc": 10.0, "editSocFlag": true}, {"id": 79680, "workMode": 2, "name": "Self-Consumption", "soc": 10.0, "editSocFlag": true}, {"id": 77244, "workMode": 3, "name": "Emergency Backup", "soc": 100.0,"editSocFlag": false} ] } } workMode 1/2/3 uses the same encoding as Mode.workMode. The id values are installation-specific and differ from the hardcoded values in the Mode factory methods (9322/9323/9324), which are correct for updateTouMode and unrelated to these schedule-entry IDs. New endpoint: updateSocV2 POST /hes-gateway/terminal/tou/updateSocV2?workMode=2&electricityType=1&soc=15 Updates the reserve SOC for a single mode without switching to that mode. electricityType=1 is always required (purpose unknown, discovered via MITM). Emergency Backup always has editSocFlag: false; the server rejects writes. Changes New: get_mode_settings() -> ModeSettings Returns a ModeSettings dataclass (consistent with the existing ExportSettings pattern) containing all mode configurations and the active mode. Convenience properties: .current_work_mode and .reserves. New: set_mode_reserve(work_mode, soc) Updates one mode's reserve without switching modes. Validates inputs before the API call and raises InvalidDataException on API failure. Fixed: get_mode() Rewritten to use get_mode_settings(). Preserves the existing (mode_name, soc) return signature. Now raises InvalidDataException (consistent with the rest of the library) instead of KeyError. New: WORK_MODE_MAP, ModeInfo, ModeSettings exported from __init__ Tested bin/test-tou-reserve.py (included) exercises all three methods against a real gateway. Confirmed working. ── get_mode_settings() ───────────────────────────────────────── current_mode_id : 83132 current_work_mode: 1 (time_of_use) reserves : {1: 10.0, 2: 10.0, 3: 100.0} modes: workMode=1 id= 83132 soc= 10.0% editable name='Free power' (user-defined tariff label) ← active workMode=2 id= 79680 soc= 10.0% editable name='Self-Consumption' workMode=3 id= 77244 soc=100.0% read-only name='Emergency Backup' Note: name is the user's custom tariff profile label as set in the FranklinWH app — it is not a fixed mode identifier. The example above shows "Free power" which is the name of this user's electricity plan. Use workMode (1/2/3) to identify the mode type reliably. get_mode() mode_name: 'time_of_use' soc : 10.0% ── set_mode_reserve(work_mode=1, soc=10) [time_of_use, no-op] Success — value written back unchanged Confirmed reserve still 10.0% ── All tests passed ────────────────────────────────────────────